use serde::{Deserialize, Serialize};
use sqlx::postgres::PgConnectOptions;
use sqlx::{PgPool, Pool, Postgres};
use tokio::fs::File;
use tokio::io::AsyncReadExt;

#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct Config {
    pub server: Option<Server>,
    pub database: Option<ConfigDatabase>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Server {
    pub url: Option<String>,
    pub host: Option<String>,
    pub port: Option<i64>,
}

#[derive(Default, Clone, Debug, Serialize, Deserialize)]
pub struct ConfigDatabase {
    pub url: Option<String>,
    pub host: Option<String>,
    pub port: Option<u16>,
    pub name: Option<String>,
    pub username: Option<String>,
    pub password: Option<String>,
}

impl Config {
    pub async fn get() -> Self {
        let mut yaml_file = File::open("config.yaml").await.expect("read config error");
        let mut yaml_str = String::new();
        yaml_file.read_to_string(&mut yaml_str).await.expect("read str error");
        serde_yml::from_str::<Config>(yaml_str.as_str()).expect("config error")
    }

    pub async fn pg_conn() -> Pool<Postgres> {
        let database = Self::get().await.database.unwrap_or_default();
        let options = PgConnectOptions::new()
            .host(&database.host.unwrap_or_default())
            .port(database.port.unwrap_or(5432))
            .database(&database.name.unwrap_or_default())
            .username(&database.username.unwrap_or_default())
            .password(&database.password.unwrap_or_default());

        PgPool::connect_with(options).await.unwrap()
        // let url = "postgres://postgres:369@localhost:5432/chat_server";
        // PgPool::connect(url).await.unwrap()
    }
}

impl Default for Server {
    fn default() -> Self {
        Self {
            url: Some("0.0.0.0:50000".to_string()),
            host: Some("0.0.0.0".to_string()),
            port: Some(50000),
        }
    }
}